package com.zbw.common.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zbw.common.entity.Book;
import com.zbw.common.entity.BookSetting;
import com.zbw.common.cache.CacheKey;
import com.zbw.common.cache.CacheService;
import com.zbw.common.config.Constants;
import com.zbw.common.entity.News;
import com.zbw.common.mapper.FrontBookMapper;
import com.zbw.common.mapper.IndexCacheMapper;
import com.zbw.common.service.IndexCacheService;
import com.zbw.common.service.NewsService;
import com.zbw.common.vo.BookSettingVO;
import com.zbw.common.vo.BookVo;
import io.github.xxyopen.web.util.BeanUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.dynamic.sql.SortSpecification;
import org.mybatis.dynamic.sql.render.RenderingStrategies;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.zbw.common.mapper.BookDynamicSqlSupport.*;
import static com.zbw.common.mapper.BookSettingDynamicSqlSupport.bookSetting;
import static org.mybatis.dynamic.sql.SqlBuilder.deleteFrom;
import static org.mybatis.dynamic.sql.SqlBuilder.isGreaterThan;
import static org.mybatis.dynamic.sql.select.SelectDSL.select;

@Service
@RequiredArgsConstructor
@Slf4j
public class indexCacheImpl implements IndexCacheService {

    private final IndexCacheMapper indexCacheMapper;

    private final CacheService cacheService;

    private final FrontBookMapper bookMapper;

    private final NewsService newsService;

    @SneakyThrows
    @Override
    public Map<Byte,List<BookSettingVO>> listIndex() {
//        cacheService.del(CacheKey.INDEX_BOOK_SETTINGS_KEY);
        String result = cacheService.get(CacheKey.INDEX_BOOK_SETTINGS_KEY);
        if (result == null || result.length() <5) {
            List<BookSettingVO> list = indexCacheMapper.listVO();
            if ( list.size() ==0){
                //没有初始化界面进行初始化设置

                list=initIndexBookSetting();
            }
            result = new ObjectMapper().writeValueAsString(
                    list.stream().collect(Collectors.groupingBy(BookSettingVO::getType)));
            cacheService.set(CacheKey.INDEX_BOOK_SETTINGS_KEY, result);
        }
        return new ObjectMapper().readValue(result, Map.class);
    }

    /**
     * 初始化首页小说设置
     */
    private List<BookSettingVO> initIndexBookSetting() {
        Date currentDate = new Date();
        List<Book> books = bookMapper.selectIdsByScoreAndRandom(Constants.INDEX_BOOK_SETTING_NUM);
        if (books.size() == Constants.INDEX_BOOK_SETTING_NUM) {
            List<BookSetting> bookSettingList = new ArrayList<>(Constants.INDEX_BOOK_SETTING_NUM);
            List<BookSettingVO> bookSettingVOList = new ArrayList<>(Constants.INDEX_BOOK_SETTING_NUM);
            for (int i = 0; i < books.size(); i++) {
                Book book = books.get(i);
                byte type;
                if (i < 4) {
                    type = 0;
                } else if (i < 14) {
                    type = 1;
                } else if (i < 19) {
                    type = 2;
                } else if (i < 25) {
                    type = 3;
                } else {
                    type = 4;
                }
                BookSettingVO bookSettingVO = new BookSettingVO();
                BookSetting bookSetting = new BookSetting();
                bookSetting.setType(type);
                bookSetting.setSort((byte) i);
                bookSetting.setBookId(book.getId());
                bookSetting.setCreateTime(currentDate);
                bookSetting.setUpdateTime(currentDate);
                bookSettingList.add(bookSetting);

                BeanUtils.copyProperties(book, bookSettingVO);
                BeanUtils.copyProperties(bookSetting, bookSettingVO);
                bookSettingVOList.add(bookSettingVO);
            }
            indexCacheMapper.delete(deleteFrom(bookSetting).build()
                    .render(RenderingStrategies.MYBATIS3));
            //将bookSetting表中数据删除
            indexCacheMapper.insertMultiple(bookSettingList);
            //将数据批量插入到bookSetting
            return bookSettingVOList;
        }
        return new ArrayList<>(0);
    }

    @Override
    public List<Book> listClickRank() {
//        cacheService.del(CacheKey.INDEX_CLICK_BANK_BOOK_KEY);
        List<Book> result = (List<Book>) cacheService.getObject(CacheKey.INDEX_CLICK_BANK_BOOK_KEY);
        if (result == null || result.size() == 0){
            result = listRank((byte)0,10);
            cacheService.setObject(CacheKey.INDEX_CLICK_BANK_BOOK_KEY,result,4000);
        }
        return result;
    }

    @Override
    public List<Book> listNewRank() {
        List<Book> result = (List<Book>) cacheService.getObject(CacheKey.INDEX_NEW_BOOK_KEY);
        if (result == null || result.size() == 0){
            result = listRank((byte)1,10);
            cacheService.setObject(CacheKey.INDEX_NEW_BOOK_KEY,result,3000);
        }
        return result;
    }

    @Override
    public List<BookVo> listUpdateRank() {
        List<BookVo> result = (List<BookVo>) cacheService.getObject(CacheKey.INDEX_UPDATE_BOOK_KEY);
        if (result == null || result.size() == 0){

            List<Book> list= listRank((byte)2,21);
            result = BeanUtil.copyList(list,BookVo.class);
            cacheService.setObject(CacheKey.INDEX_UPDATE_BOOK_KEY,result,1000);
        }
        return result;
    }

    @Override
    public List<News> listIndexNews() {
        List<News> result = (List<News>) cacheService.getObject(CacheKey.INDEX_NEWS_KEY);
        if (result == null || result.size() == 0){

            List<News> list= newsService.listIndexNews();
            result = BeanUtil.copyList(list,News.class);
            cacheService.setObject(CacheKey.INDEX_NEWS_KEY,result,1000);
        }
        return result;
    }

    @Override
    public List<Book> listRank(Byte type, Integer limit) {
        SortSpecification sortSpecification = visitCount.descending();
        switch (type) {
            case 1: {
                //最新入库排序
                sortSpecification = createTime.descending();
                break;
            }
            case 2: {
                //最新更新时间排序
                sortSpecification = lastIndexUpdateTime.descending();
                break;
            }
            case 3: {
                //评论数量排序
                sortSpecification = commentCount.descending();
                break;
            }
            default: {
                break;
            }
        }
        SelectStatementProvider selectStatement = select(id, catId, catName, bookName, lastIndexId, lastIndexName,
                authorId, authorName, picUrl, bookDesc, wordCount, lastIndexUpdateTime)
                .from(book)
                .where(wordCount, isGreaterThan(0))
                .orderBy(sortSpecification)
                .limit(limit)
                .build()
                .render(RenderingStrategies.MYBATIS3);
        return bookMapper.selectMany(selectStatement);

    }
}
